package com.zhouheng.springbootmultithreading.module.producerconsumerissues.service.impl;

import com.zhouheng.springbootmultithreading.module.producerconsumerissues.service.Storage;

import java.util.concurrent.LinkedBlockingQueue;

/**
 * 阻塞队列仓库，内部实现方式和await signal相同
 *
 * @author 周恒
 * @date 20190108 14:58:58
 * @since v1.0
 */
public class LinkedBlockingQueueStorageImpl implements Storage {

    /**
     * MAX_SIZE 仓库最大存储量
     */
    private int MAX_SIZE;

    public LinkedBlockingQueueStorageImpl(int MAX_SIZE) {
        this.MAX_SIZE = MAX_SIZE;
        this.list = new LinkedBlockingQueue<>(this.MAX_SIZE);
    }

    /**
     * list 仓库存储的载体 阻塞队列
     */
    private LinkedBlockingQueue<Object> list;

    @Override
    public void produce(String producer) {
        // 如果仓库已满
        if (list.size() == MAX_SIZE) {
            System.out.println("仓库已满，【" + producer + "】： 暂时不能执行生产任务!");
        }
        // 生产产品
        try {
            //put：如果满了自动进入阻塞，直到有被取出后，才插入一条
            list.put(new Object());
            //offer()：队满时返回false
            System.out.println("【" + producer + "】：生产了一个产品\t【现仓储量为】:" + list.size());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void consume(String consumer) {
        // 如果仓库存储量不足
        if (list.size() == 0) {
            System.out.println("仓库已空，【" + consumer + "】： 暂时不能执行消费任务!");
        }
        try {
            //take：如果空了自动进入阻塞，直到有数据后，再取出一条
            list.take();
            //poll()：弹出队顶元素，队列为空时，返回空
            //peek()：和poll烈性，返回队队顶元素，但顶元素不弹出。队列为空时返回null
            //remove(Object o)：移除某个元素，队列为空时抛出异常。成功移除返回true
            System.out.println("【" + consumer + "】：消费了一个产品\t【现仓储量为】:" + list.size());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}
